package gwall.cloud.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.json.JsonMapper;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;

@Slf4j
public abstract class IfyouJsonUtils {

    private static ObjectMapper mapper;

    static {
//        mapper = new ObjectMapper();
//        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//        // 忽略不存在的字段
//        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//        // java: com.fasterxml.jackson.databind.ObjectMapper中的configure(com.fasterxml.jackson.databind.MapperFeature,boolean)已过时
//        // mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
//
//        mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);

        mapper = JsonMapper.builder()
                .serializationInclusion(JsonInclude.Include.NON_NULL)
                // 反序列化时忽略大小写
                .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
                // 忽略不存在的字段
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                .build();
    }

    public static String toJson(Object src) {
        try {
            return mapper.writeValueAsString(src);
        } catch (Exception e) {
            log.error("[toJson] e = ", e);
        }

        return null;
    }

    public static <T> T toObject(String json, Class<T> type) {
        log.info("[toObject] enter, json = {}", json);

        try {
            return mapper.readValue(json, type);
        } catch (Exception e) {
            log.error("[toObject] throw Exception, e = ", e);
        }

        return null;
    }

    public static <T> T toObject(String json, TypeReference<T> valueTypeRef) {
        log.info("[toObject valueTypeRef] enter, json = {}", json);

        try {
            return mapper.readValue(json, valueTypeRef);
        } catch (Exception e) {
            log.error("[toObject] throw Exception, e = ", e);
        }

        return null;
    }

    public static <T> List<T> toList(String json, Class<T> type) {
        try {
            JavaType valueType = mapper.getTypeFactory().constructCollectionType(List.class, type);

            return mapper.readValue(json, valueType);
        } catch (Exception e) {
            log.error("[toList] throw Exception, e = ", e);
        }

        return null;
    }

    public static <K, V> Map<K, V> toMap(String json, Class<K> key, Class<V> value) {
        try {
            JavaType valueType = mapper.getTypeFactory().constructMapType(Map.class, key, value);

            return mapper.readValue(json, valueType);
        } catch (Exception e) {
            log.error("[toMap] throw Exception, e = ", e);
        }

        return null;
    }

    public static Boolean hasKey(String json, String key) {
        log.info("[hasKey] enter, json = {}, key = {}", json, key);

        try {
            JsonNode jsonNode = mapper.readTree(json);

            return jsonNode.has(key);
        } catch (Exception e) {
            log.error("[hasKey] throw Exception, key = {}, e = ", key, e);
        }

        return null;
    }

    public static String getByKey(String json, String key) {
        log.info("[getByKey] enter, json = {}, key = {}", json, key);

        try {
            JsonNode jsonNode = mapper.readTree(json);
            if (jsonNode.has(key)) {
                return jsonNode.get(key).asText();
            }
        } catch (Exception e) {
            log.error("[hasKey] throw Exception, key = {}, e = ", key, e);
        }

        return null;
    }

}

